package cn.miju.admin.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.miju.admin.system.service.GroupService;
import cn.miju.admin.system.vo.*;
import cn.miju.database.entity.SysGroup;
import cn.miju.database.entity.SysUserAuthGroup;
import cn.miju.database.mapper.SysGroupMapper;
import cn.miju.database.mapper.SysUserAuthGroupMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <pre>
 * 组织管理
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-04-04 16:34
 */
@Service
@RequiredArgsConstructor
public class GroupServiceImpl implements GroupService {
    private final SysGroupMapper sysGroupMapper;
    private final SysUserAuthGroupMapper sysUserAuthGroupMapper;
    /**
     * 组织分页查询
     * @param inVO {@link GroupPageInVO}
     * @return {@link Page<GroupPageOutVO>}
     */
    @Override
    public Page<GroupPageOutVO> getPage(GroupPageInVO inVO) {
        LambdaQueryWrapper<SysGroup> queryWrapper = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(inVO.getKeyword())) {
            queryWrapper.like(SysGroup::getGroupName, inVO.getKeyword());
        }
        queryWrapper.isNull(SysGroup::getParentId);
        Page<SysGroup> sysGroupPage = sysGroupMapper.selectPage(new Page<>(inVO.getPage(), inVO.getPageSize()), queryWrapper);
        Page<GroupPageOutVO> page = new Page<>();
        BeanUtil.copyProperties(sysGroupPage, page);
        if (CollUtil.isNotEmpty(sysGroupPage.getRecords())) {
            List<Long> groupIdList = sysGroupPage.getRecords().stream().map(SysGroup::getId).collect(Collectors.toList());
            List<SysGroup> secondSysGroupList = sysGroupMapper.selectList(Wrappers.<SysGroup>lambdaQuery().in(SysGroup::getParentId, groupIdList));
            Map<Long, List<SysGroup>> groupIdMap = Maps.newHashMap();
            if (CollUtil.isNotEmpty(secondSysGroupList)) {
                groupIdMap = secondSysGroupList.stream().collect(Collectors.groupingBy(SysGroup::getParentId, Collectors.mapping(sysGroup -> sysGroup, Collectors.toList())));
            }
            Map<Long, List<SysGroup>> finalGroupIdMap = groupIdMap;
            page.setRecords(sysGroupPage.getRecords().stream().map(sysGroup -> {
                GroupPageOutVO outVO = new GroupPageOutVO();
                outVO.setId(sysGroup.getId());
                outVO.setParentId(sysGroup.getParentId());
                outVO.setGroupName(sysGroup.getGroupName());
                outVO.setStatus(sysGroup.getStatus());
                outVO.setSort(sysGroup.getSort());
                outVO.setCreatedTime(sysGroup.getCreatedTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                outVO.setRemark(sysGroup.getRemark());
                List<SysGroup> secondSysGroupLists = finalGroupIdMap.getOrDefault(sysGroup.getId(), Lists.newArrayList());
                outVO.setChildren(secondSysGroupLists.stream().map(secondSysGroup -> {
                    GroupPageOutVO secondOutVO = new GroupPageOutVO();
                    secondOutVO.setId(secondSysGroup.getId());
                    secondOutVO.setParentId(secondSysGroup.getParentId());
                    secondOutVO.setGroupName(secondSysGroup.getGroupName());
                    secondOutVO.setStatus(secondSysGroup.getStatus());
                    secondOutVO.setSort(secondSysGroup.getSort());
                    secondOutVO.setCreatedTime(secondSysGroup.getCreatedTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    secondOutVO.setRemark(secondSysGroup.getRemark());
                    return secondOutVO;
                }).collect(Collectors.toList()));
                return outVO;
            }).collect(Collectors.toList()));
        }
        return page;
    }

    /**
     * 一级组织树查询
     * @return {@link List<GroupTreeOutVO>}
     */
    @Override
    public List<GroupTreeOutVO> getFirstTree() {
        LambdaQueryWrapper<SysGroup> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.isNull(SysGroup::getParentId);
        List<SysGroup> sysGroupList = sysGroupMapper.selectList(queryWrapper);
        List<GroupTreeOutVO> outVOList = Lists.newArrayList();
        if (CollUtil.isNotEmpty(sysGroupList)) {
            outVOList.addAll(sysGroupList.stream().map(sysGroup -> {
                GroupTreeOutVO outVO = new GroupTreeOutVO();
                outVO.setId(sysGroup.getId());
                outVO.setLabel(sysGroup.getGroupName());
                return outVO;
            }).collect(Collectors.toList()));
        }

        return outVOList;
    }

    /**
     * 组织树查询
     * @return {@link List<GroupTreeOutVO>}
     */
    @Override
    public List<GroupTreeOutVO> getTree() {
        LambdaQueryWrapper<SysGroup> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.isNull(SysGroup::getParentId);
        List<SysGroup> sysGroupList = sysGroupMapper.selectList(queryWrapper);
        List<GroupTreeOutVO> outVOList = Lists.newArrayList();
        if (CollUtil.isNotEmpty(sysGroupList)) {
            List<Long> groupIdList = sysGroupList.stream().map(SysGroup::getId).collect(Collectors.toList());
            List<SysGroup> secondSysGroupList = sysGroupMapper.selectList(Wrappers.<SysGroup>lambdaQuery().in(SysGroup::getParentId, groupIdList));
            Map<Long, List<SysGroup>> groupIdMap = Maps.newHashMap();
            if (CollUtil.isNotEmpty(secondSysGroupList)) {
                groupIdMap = secondSysGroupList.stream().collect(Collectors.groupingBy(SysGroup::getParentId, Collectors.mapping(sysGroup -> sysGroup, Collectors.toList())));
            }
            Map<Long, List<SysGroup>> finalGroupIdMap = groupIdMap;
            outVOList.addAll(sysGroupList.stream().map(sysGroup -> {
                GroupTreeOutVO outVO = new GroupTreeOutVO();
                outVO.setId(sysGroup.getId());
                outVO.setParentId(sysGroup.getParentId());
                outVO.setLabel(sysGroup.getGroupName());
                List<SysGroup> secondSysGroupLists = finalGroupIdMap.getOrDefault(sysGroup.getId(), Lists.newArrayList());
                outVO.setChildren(secondSysGroupLists.stream().map(secondSysGroup -> {
                    GroupTreeOutVO secondOutVO = new GroupTreeOutVO();
                    secondOutVO.setId(secondSysGroup.getId());
                    secondOutVO.setParentId(secondSysGroup.getParentId());
                    secondOutVO.setLabel(secondSysGroup.getGroupName());
                    return secondOutVO;
                }).collect(Collectors.toList()));
                return outVO;
            }).collect(Collectors.toList()));
        }
        return outVOList;
    }

    /**
     * 保存
     * @param inVO {@link GroupSaveInVO}
     */
    @Override
    public void save(GroupSaveInVO inVO) {
        SysGroup sysGroup = SysGroup.builder().
                id(inVO.getId()).
                parentId(inVO.getParentId()).
                groupName(inVO.getGroupName()).
                sort(inVO.getSort()).
                remark(inVO.getRemark()).
                status(inVO.getStatus()).
                build();
        if (null == inVO.getId()) {
            sysGroupMapper.insert(sysGroup);
        } else {
            sysGroupMapper.updateById(sysGroup);
        }
    }

    /**
     * 批量删除
     * @param inVO {@link GroupDeleteInVO}
     */
    @Override
    public void deletes(GroupDeleteInVO inVO) {
        sysGroupMapper.deleteBatchIds(inVO.getIds());
        sysUserAuthGroupMapper.delete(Wrappers.<SysUserAuthGroup>lambdaQuery().
                in(SysUserAuthGroup::getGroupId, inVO.getIds()));
    }
}
